//Erik J. Wright
//data_node.h

/*
This headder file describes a linear linked list of
command parameters to be sent to a PWM controller.
These commands are specifically intended to be used 
by the Lynxmotion SSC-32 servo controller.  If you 
use a different controller board you may want to change 
the exact command, though the pulse width value of 
the command may remain the same.

This class is intended to be inherited by classes
describing a continuous rotational servo or a 
discrete angle servo. 


Here is an overview of the control syntax for the SSC-32:

Each event consists of:
<ch>	Channel Number in decimal, 0-31
<pw>	Pulse width in microseconds, 500 to 2500
<spd>	Movement speed in uS per second for one channel (optional)
<time>	Time in mS for the entire move, affects all channels, 65535 MAX
<cr>	Carriage return character, ASCII 13. (Required to initiate action)
<esc>	Cancel the current command, ASCII 27. 

	(Data sheet: "Lynxmotion SSC-32 (Ver 2.0)", pg. 5)
Serial Data Format
	Servo Move:	#<ch> P<pw> S<spd>
	Group Move:	#<ch> #<ch> P<pw> S<spd> T<time><cr>

Note:  This controller is designed for angled servos.  For this project, continuous rotation servos have been chosen to lift the limbs of the robot, and only angled servos have been chosen for the inner body.
	Angled Servo:	pulse_width = 1500 is dead center, each uSec corresponds to some amount of angle.
	Continuous Rot:	pulse_width = 1500 is no rotation, each uSec of PWM correponds to some RPM.
*/

class data_node 
{
	private:
	//data elements
	data_node* next;	//pointer to the next element
	int pw_val;		//pulse width value in microseconds
	int sweeptime;		//time until target pw_val is reached  



	//functions
	void display_event();			//formats and displays the event to standard out
	void recursive_delete(data_node*&); 			//recursive function to delete list
	void insert_at_end_recur(data_node*, data_node *&);	//recursively inserts at end
	void recur_avg(data_node*&, data_node*&, data_node*&);
	void recursive_inorder_display(data_node* );
	void recur_deep_cpy(data_node*&, data_node*);	//recursively perform deep copy
	data_node* goto_event(data_node*, int);
	data_node* remove_from_swappoint(data_node*&, int);

	public:
	~data_node();		//class deconstructor
	data_node();		//class constructor
	data_node(int pw_val, int event_time);	//loaded constructor
	data_node(const data_node&);	//class copy constructor
	int lengthof(data_node*);		//finds the lenght of the list
	void insert_at_end(data_node *&);	//insert a node, or many, at the end of given list
	void inorder_display();		//display entire list
	void binary_twist(data_node*&, bool);	
	void binary_twist_rand(data_node*& given, bool keep_length);
	void average_twist(data_node*&);
	void weighted_average_twist(data_node*&, int);
	int get_time();		//returns the value of the time in node
	int get_pw();		//returns pw value in node
	bool is_last(data_node*& );		//true if last node in list
	data_node* next_node();	//set pointer to next node
};




/*
pwm_servo
This class manages the data nodes.  Most of the functions just act as
wrappers to lower functions.  However, the main goal of this class is 
to keep track of the current state of the string.  We want to know
the displacement and velocity.
*/
class pwm_servo
{
	private:
	data_node* head;	//beginning of the list
	data_node* parser;
	
	//functions
	void kill_list(); 	//recursive function to delete list

	public:
	~pwm_servo();		//class deconstructor
	pwm_servo();		//class constructor
	pwm_servo(const pwm_servo&);	//class copy constructor
	int lengthof();		//finds the lenght of the list
	void display();		//formats and displays the event to standard ou
	void insert_at_end(data_node *&);	//insert a node, or many, at the end of given list
	void randomize();	//creates new random sequence
	void binary_twist(pwm_servo&, bool);	
	void binary_twist_rand(pwm_servo& given, bool preserve);
	void average_twist(pwm_servo&);
	void weighted_average_twist(pwm_servo&, int);
	int get_pw();		//get's the pw value from parser
	int get_time();		//get's the time value from parser
	void set_parser();	//point parser to beginning of list
	bool traverse();		//move parser to next item in list
	

};
